package yxy.banana.socket.handler;

import com.google.protobuf.ByteString;
import com.google.protobuf.MessageLite;

import io.netty.channel.ChannelPromise;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import yxy.apple.nio.LayeredHandler;
import yxy.apple.protobuf.Message;
import yxy.apple.protobuf.Message.Parcal;
import yxy.banana.socket.NetworkElement;
import yxy.banana.socket.ParcalUtility;

public abstract class ParcalHandler extends LayeredHandler {

	@Deprecated
	@Override
	public void receive(Object message) throws Exception {
		if (message != null && message instanceof Parcal) {
			Parcal parcal = (Parcal) message;
			this.receive(parcal);
		} else {
			this.drop(message);
		}
	}

	/**
	 * 组装并发送消息
	 * 
	 * @param tag
	 * @param source
	 * @param destination
	 * @param proto
	 * @param message
	 * @return 发送消息时产生的sequence
	 * @throws Exception
	 */
	public int send(String tag, long source, long destination, int proto, MessageLite message) throws Exception {
		return this.send(tag, source, destination, proto, message.toByteString());
	}

	/**
	 * 
	 * 组装并发送消息
	 * 
	 * @param tag
	 * @param source
	 * @param destination
	 * @param proto
	 * @param data
	 * @return 发送消息时产生的sequence
	 * @throws Exception
	 */
	public int send(String tag, long source, long destination, int proto, ByteString data) throws Exception {
		Parcal parcal = ParcalUtility.build(tag, source, destination, proto, data);
		this.send(parcal);
		return parcal.getSequence();
	}

	public void send(Parcal message) throws Exception {
		super.send(message, null, true);
	}

	@Override
	@Deprecated
	public void send(Object message) throws Exception {
		super.send(message);
	}

	@Override
	@Deprecated
	public void send(Object message, ChannelPromise promise, boolean flush) throws Exception {
		super.send(message, promise, flush);
	}

	@Override
	@Deprecated
	public void send(Object message, ChannelPromise promise, boolean flush, GenericFutureListener<? extends Future<? super Void>> listener)
			throws Exception {
		super.send(message, promise, flush, listener);
	}

	protected abstract void receive(Parcal parcal) throws Exception;

	protected abstract void drop(Object message);

	public abstract int system();

	public abstract int cluster();

	public abstract int channel();

	@Override
	public String toString() {
		return String.format("{class:\"%s\", ne:\"%s\", local:\"%s\", remote:\"%s\"}", this.getClass().getSimpleName(),
				NetworkElement.assemble(this.system(), this.cluster(), this.channel()).toString(), this.localAddress(),
				this.remoteAddress());
	}
}
